package com.enbatis.mybatisplugs.config.intercepors;

import com.enbatis.mybatisplugs.base.Account;
import com.enbatis.mybatisplugs.base.IRedisService;
import com.enbatis.mybatisplugs.commons.utils.MD5Util;
import com.enbatis.mybatisplugs.commons.utils.ResultReturn;
import com.enbatis.mybatisplugs.toolkit.CusAccessObjectUtil;
import com.enbatis.mybatisplugs.toolkit.LoginCacheUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.sonatype.inject.Nullable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@Component
@Slf4j
public class Interceptor implements HandlerInterceptor {
    @Autowired
    protected IRedisService redisService;


    //这个方法是在访问接口之前执行的，我们只需要在这里写验证登陆状态的业务逻辑，就可以在用户调用指定接口之前验证登陆状态了
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //每一个项目对于登陆的实现逻辑都有所区别，我这里使用最简单的Session提取User来验证登陆。
        String referer= request.getHeader("Referer");
        String userAgent= request.getHeader("User-Agent");
        response.setCharacterEncoding("UTF-8");
        response.setContentType("text/html;charset=utf-8");
        String ip=  CusAccessObjectUtil.getIpFromRequest(request);
        String ru=request.getRequestURI();
        if (ru.contains("/location_receive")){
            return true;
        }
      List listBlack=  redisService.getList("blackList");
      boolean blackHave = CollectionUtils.isNotEmpty(listBlack);
      if (blackHave){
         if (listBlack.contains(MD5Util.MD5(ip+"-blackList-"+userAgent))){
             response.getWriter().write(ResultReturn.warring("您已被加入黑名单请一天之后重试"));
             return false;
         }
      }
       List list= redisService.getList(ip);
       if (CollectionUtils.isEmpty(list)){
           redisService.setList(ip, Lists.newArrayList(1),60L);
       }else {

         List haveList=  redisService.add(ip,1);
           if (haveList.size()>60 && haveList.size()<100){
               response.getWriter().write(ResultReturn.warring("您的操作太快，休息一下吧"));
               return false;
           }else if ( haveList.size()>100){
               response.getWriter().write(ResultReturn.warring("您存在恶意攻击已被加入黑名单，请一年之后再试"));
               if (blackHave){
                   redisService.add("blackList",MD5Util.MD5(ip+"-blackList-"+userAgent));
               }else{
                   redisService.setList("blackList", Lists.newArrayList(MD5Util.MD5(ip+"-blackList-"+userAgent)),31536000L);
               }
               return  false;
           }

       }


       if (ru.contains( "/v1/login/login")||ru.contains("/v1/login/createCode")||
               ru.contains("/register")||ru.contains("/app_login")||
               ru.contains("/location_receive")||
               ru.contains("/tologin")||
               ru.contains("/test")||
               ru.contains("/upload")||
               ru.contains("/android_login_log_list")){
           return true;
       }

        Cookie[] cookies = request.getCookies();
        //如果session中没有user，表示没登陆
        if (cookies != null){
            for (Cookie cookie:cookies) {
                Account user=  LoginCacheUtil.loginUser.get(cookie.getValue());
                if (null!=user){
                        return true;
                }
            }

            return  false;
            //这个方法返回false表示忽略当前请求，如果一个用户调用了需要登陆才能使用的接口，如果他没有登陆这里会直接忽略掉
            //当然你可以利用response给用户返回一些提示信息，告诉他没登陆
        }else {
            if (ru.contains("/login/login")){

                return true;
            }else{
                response.getWriter().write("未登录");
                return false;    //如果session里有user，表示该用户已经登陆，放行，用户即可继续调用自己需要的接口
            }


        }
    }

    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable ModelAndView modelAndView) throws Exception {
    }

    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, @Nullable Exception ex) throws Exception {
    }



}
